﻿#ifndef _PING_H_
#define _PING_H_

#include <stdint.h>
// #include <winsock2.h>
// #include <WS2tcpip.h>

#include "net_api.h"

#define IPV4_ADDR_SIZE 4
#define PING_BUFFER_SIZE 10240
#define PING_DEFAULT_ID 0x0000
#define PING_RECV_TMO 3000

#pragma pack(1)

// icmpv4协议包头结构
typedef struct _ping_icmpv4_hdr_t
{
    uint8_t type;      // 类型
    uint8_t code;      // 代码
    uint16_t checksum; // 校验和
    uint16_t id;
    uint16_t seq;
} ping_icmpv4_hdr_t;

// ipv4 报文头结构
typedef struct _ping_ipv4_hdr_t
{
    union
    {
        struct
        {
            uint16_t shdr : 4;
            uint16_t version : 4; // 单位4字节,报文头长度
            uint16_t tos : 8;
        };
        uint16_t shdr_all;
    };

    uint16_t total_len; // 总长度,单位字节
    uint16_t id;        //

    union
    {
        struct
        {
            uint16_t offset : 13; // 分片数据包的偏移量,单位8字节
            uint16_t more : 1;    // 后面有无其他分片包
            uint16_t disable : 1; // 是否允许分片
            uint16_t reverse : 1; // 保留位,固定值为0
        };
        uint16_t frag_all;
    };

    uint8_t ttl;           // 生存时间
    uint8_t protocol;      // 协议
    uint16_t hdr_checksum; // 头部校验和
    uint8_t src_ip[IPV4_ADDR_SIZE];
    uint8_t dst_ip[IPV4_ADDR_SIZE];
    // 忽略选项
} ping_ipv4_hdr_t;

// ip相关交给上层填充
typedef struct _echo_req_t
{
    ping_icmpv4_hdr_t echo_hdr;
    char buf[PING_BUFFER_SIZE];
} echo_req_t;

typedef struct _echo_reply_t
{
    ping_ipv4_hdr_t iphdr;
    ping_icmpv4_hdr_t echo_hdr;
    char buf[PING_BUFFER_SIZE];
} echo_reply_t;

typedef struct _pint_t
{
    echo_req_t req;
    echo_reply_t reply;
} ping_t;

#pragma pack()

void ping_run(ping_t *ping, const char *dest, int count, int size, int interval);

#endif